2020 excess mortality & voting patterns in CH
Redistributed cantonal deaths
Data
Canton
Expected deaths by age X sex X canton in 2020 from Riou et al..
Contains iterations of diff results
max(exp_deaths_2020_kt$it)[1] 1000
Example of one iteration
| Name | Piped data |
| Number of rows | 260 |
| Number of columns | 6 |
| _______________________ | |
| Column type frequency: | |
| character | 3 |
| numeric | 3 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| canton | 0 | 1 | 2 | 2 | 0 | 26 | 0 |
| age_group | 0 | 1 | 3 | 5 | 0 | 5 | 0 |
| sex | 0 | 1 | 4 | 6 | 0 | 2 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| it | 0 | 1 | 1.00 | 0.00 | 1 | 1.00 | 1.0 | 1.00 | 1 | ▁▁▇▁▁ |
| exp_deaths | 0 | 1 | 216.61 | 399.69 | 0 | 22.75 | 75.5 | 217.25 | 2857 | ▇▁▁▁▁ |
| observed2 | 0 | 1 | 254.35 | 491.21 | 0 | 23.00 | 81.0 | 247.75 | 3891 | ▇▁▁▁▁ |
Municipality
Data prepared in 02.Rmd. Collapsing age groups and
renaming variables to match cantonal estimates.
w_deaths_2020_year_fin = read_rds("data/BfS-closed/monthly_deaths/w_deaths_2015_2020_year_fin.Rds") %>%
filter(year == 2020) %>% select(-year) %>%
rename(age_group = age,
canton = KTNAME) %>%
mutate(age_group = if_else(age_group == "40-49", "40-59", age_group),
age_group = if_else(age_group == "50-59", "40-59", age_group)) %>%
group_by(canton, GMDNR, age_group, sex) %>%
summarise(observed = sum(observed),
pop_mid_poi = sum(pop_mid_poi)) %>%
ungroup()| Name | Piped data |
| Number of rows | 21450 |
| Number of columns | 6 |
| _______________________ | |
| Column type frequency: | |
| character | 3 |
| numeric | 3 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| canton | 0 | 1 | 2 | 2 | 0 | 26 | 0 |
| age_group | 0 | 1 | 3 | 5 | 0 | 5 | 0 |
| sex | 0 | 1 | 4 | 6 | 0 | 2 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| GMDNR | 0 | 1 | 3289.82 | 2133.49 | 1 | 1067 | 3296 | 5411 | 6810 | ▇▃▅▅▇ |
| observed | 0 | 1 | 3.55 | 18.99 | 0 | 0 | 1 | 3 | 1493 | ▇▁▁▁▁ |
| pop_mid_poi | 0 | 1 | 403.70 | 1769.38 | 0 | 44 | 123 | 336 | 116058 | ▇▁▁▁▁ |
Spatial
kt = read_rds("data/BfS/kt.Rds")
gg = read_rds("data/BfS/gg.Rds")
tg3o = read_rds("data/BfS/tg3o.Rds")
se_alt = read_rds("data/BfS/se_alt.Rds")Downscale function
@jriou method to downscale cantonal deaths to municipality level.
source("R/downscale_year.R")Downscale
exp_deaths_2020_year = downscale_year(exp_deaths_2020_kt, w_deaths_2020_year_fin)Again, result contains iterations of diff results
max(exp_deaths_2020_year$it)[1] 1000
Example of one iteration
| Name | Piped data |
| Number of rows | 21450 |
| Number of columns | 12 |
| _______________________ | |
| Column type frequency: | |
| character | 3 |
| numeric | 9 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| canton | 0 | 1 | 2 | 2 | 0 | 26 | 0 |
| age_group | 0 | 1 | 3 | 5 | 0 | 5 | 0 |
| sex | 0 | 1 | 4 | 6 | 0 | 2 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| GMDNR | 0 | 1.00 | 3289.82 | 2133.49 | 1 | 1067 | 3296.00 | 5411.00 | 6810 | ▇▃▅▅▇ |
| observed | 0 | 1.00 | 3.55 | 18.99 | 0 | 0 | 1.00 | 3.00 | 1493 | ▇▁▁▁▁ |
| pop_mid_poi | 0 | 1.00 | 403.70 | 1769.38 | 0 | 44 | 123.00 | 336.00 | 116058 | ▇▁▁▁▁ |
| it | 0 | 1.00 | 1.00 | 0.00 | 1 | 1 | 1.00 | 1.00 | 1 | ▁▁▇▁▁ |
| exp_deaths | 0 | 1.00 | 404.91 | 589.00 | 0 | 65 | 182.00 | 471.00 | 2857 | ▇▁▁▁▁ |
| observed2 | 0 | 1.00 | 467.83 | 712.77 | 0 | 62 | 173.00 | 547.00 | 3891 | ▇▁▁▁▁ |
| p | 9988 | 0.53 | 0.02 | 0.06 | 0 | 0 | 0.01 | 0.02 | 1 | ▇▁▁▁▁ |
| munici_exp_deaths | 0 | 1.00 | 2.63 | 13.31 | 0 | 0 | 0.00 | 2.00 | 856 | ▇▁▁▁▁ |
| munici_excess | 0 | 1.00 | 0.93 | 6.84 | -17 | 0 | 0.00 | 1.00 | 637 | ▇▁▁▁▁ |
Preps
Aggregates
Iterations collapsed for each municipality strata.
exp_deaths_2020_year_agg = exp_deaths_2020_year %>%
rename(munici_observed = observed,
cant_exp_deaths = exp_deaths,
cant_observed = observed2) %>%
group_by(canton, GMDNR, age_group, sex) %>%
summarise(
# observed
munici_observed = first(munici_observed),
population = first(pop_mid_poi),
# modelled x1000
# expected
munici_expected_lo = quantile(munici_exp_deaths, 0.025),
munici_expected_med = quantile(munici_exp_deaths, 0.5),
munici_expected_up = quantile(munici_exp_deaths, 0.975),
# excess
munici_excess_lo = quantile(munici_excess, 0.025),
munici_excess_med = quantile(munici_excess, 0.5),
munici_excess_up = quantile(munici_excess, 0.975)
) %>%
ungroup()Even simpler aggregation to municipality level, ignoring age & sex strata.
exp_deaths_2020_year_gem = exp_deaths_2020_year_agg %>%
group_by(canton, GMDNR) %>%
summarise(
# community level totals
population = sum(population),
munici_observed = sum(munici_observed),
munici_expected_med = sum(munici_expected_med),
munici_excess_med = sum(munici_excess_med)
) %>%
ungroup() %>%
# ratio and per pop
mutate(munici_excess_rat = munici_excess_med / munici_expected_med,
munici_excess_pop = (munici_excess_med / population) * 1000) Special situation arises in this aggregation when calculating a
ratio of excess deaths to observed deaths. There are
communities where expected number of deaths is zero. That leads to ratio
being Inf in cases where excess is > 0 and to
NaN where excess is (also) == 0.
munici_expected_med == 0 <lgl>
# total N=2145 valid N=2145 mean=0.05 sd=0.21
Value | N | Raw % | Valid % | Cum. %
---------------------------------------
FALSE | 2042 | 95.20 | 95.20 | 95.20
TRUE | 103 | 4.80 | 4.80 | 100.00
<NA> | 0 | 0.00 | <NA> | <NA>
These communities’ ratios were recoded to NA.
Bring covariates
exp_deaths_2020_year_agg %<>%
left_join(read_rds("data/BfS-closed/monthly_deaths/w_deaths_2015_2020_year_fin.Rds") %>%
select(GMDNR, GMDNAME, border,
median_ssep3_q, r_urban1, r_urban2, r_lang) %>%
distinct())
exp_deaths_2020_year_gem %<>%
left_join(read_rds("data/BfS-closed/monthly_deaths/w_deaths_2015_2020_year_fin.Rds") %>%
select(GMDNR, GMDNAME, border,
median_ssep3_q, r_urban1, r_urban2, r_lang) %>%
distinct())Bring voting
covid_jun = read_rds("data/voting/covid_jun.Rds") %>%
select(GMDNR, jaStimmenInProzent, vote_yes) %>%
rename(vote_yes_jun_perc = jaStimmenInProzent,
vote_yes_jun_cat = vote_yes)
covid_nov = read_rds("data/voting/covid_nov.Rds") %>%
select(GMDNR, jaStimmenInProzent, vote_yes) %>%
rename(vote_yes_nov_perc = jaStimmenInProzent,
vote_yes_nov_cat = vote_yes)Note: there are few small communities with no voting info - these were excluded.
# A tibble: 4 × 2
canton GMDNAME
<chr> <chr>
1 BE Meienried
2 BE Hellsau
3 BE Deisswil bei Münchenbuchsee
4 BE Niedermuhlern
Excess deaths per 1000 pop
Distribution
Maps
x <categorical>
# total N=2141 valid N=2141 mean=3.00 sd=1.41
Value | N | Raw % | Valid % | Cum. %
---------------------------------------------
[0.00, 1.49) | 429 | 20.04 | 20.04 | 20.04
[1.49, 2.08) | 428 | 19.99 | 19.99 | 40.03
[2.08, 2.64) | 428 | 19.99 | 19.99 | 60.02
[2.64, 3.52) | 428 | 19.99 | 19.99 | 80.01
[3.52,27.78] | 428 | 19.99 | 19.99 | 100.00
<NA> | 0 | 0.00 | <NA> | <NA>
Choropleth
Proportional symbols
Symbol size perceptually scaled to population size.
EDA June vote
Map
Correlations
Unweighted
cor.test(exp_deaths_2020_year_gem$munici_excess_pop,
exp_deaths_2020_year_gem$vote_yes_jun_perc,
method = "pearson")
Pearson's product-moment correlation
data: exp_deaths_2020_year_gem$munici_excess_pop and exp_deaths_2020_year_gem$vote_yes_jun_perc
t = 0.63465, df = 2139, p-value = 0.5257
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
-0.02865836 0.05605123
sample estimates:
cor
0.01372105
Weighted
wtd.cor(exp_deaths_2020_year_gem$munici_excess_pop,
exp_deaths_2020_year_gem$vote_yes_jun_perc,
weight = exp_deaths_2020_year_gem$munici_observed) correlation std.err t.value p.value
Y 0.005492431 0.02188932 0.2509183 0.8019019
Scatter
Unweighted
Weighted
Box
EDA Nov vote
Map
Correlations
Unweighted
cor.test(exp_deaths_2020_year_gem$munici_excess_pop,
exp_deaths_2020_year_gem$vote_yes_nov_perc,
method = "pearson")
Pearson's product-moment correlation
data: exp_deaths_2020_year_gem$munici_excess_pop and exp_deaths_2020_year_gem$vote_yes_nov_perc
t = -3.6713, df = 2139, p-value = 0.0002473
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
-0.12108777 -0.03689184
sample estimates:
cor
-0.07913093
Weighted
wtd.cor(exp_deaths_2020_year_gem$munici_excess_pop,
exp_deaths_2020_year_gem$vote_yes_nov_perc,
weight = exp_deaths_2020_year_gem$munici_observed) correlation std.err t.value p.value
Y -0.130383 0.02170279 -6.007662 0.000000002214821